package cn.dinxian.activiti.service.impl;

import cn.dinxian.api.DeploymentService;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import cn.dinxian.entity.ActReDeploymentVO;
import cn.dinxian.activiti.domain.dto.ProcessDefinitionDTO;
import cn.dinxian.activiti.mapper.ActReDeploymentMapper;

import cn.dinxian.activiti.service.IProcessDefinitionService;
import cn.dinxian.api.HistoryService;
import cn.dinxian.api.RepositoryService;
import cn.dinxian.api.RuntimeService;
import cn.dinxian.common.config.RuoYiConfig;
import cn.dinxian.common.core.page.PageDomain;
import cn.dinxian.common.utils.file.FileUploadUtils;
//import org.activiti.engine.HistoryService;
//import org.activiti.engine.RepositoryService;
//import org.activiti.engine.RuntimeService;
//import org.activiti.engine.history.HistoricProcessInstance;
//import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntityImpl;
//import org.activiti.engine.repository.ProcessDefinition;
//import org.activiti.engine.repository.ProcessDefinitionQuery;
//import org.activiti.engine.runtime.ProcessInstance;
import cn.dinxian.entity.BaseDTO;
import cn.dinxian.entity.CommonResult;
import cn.dinxian.entity.MyProcessDefinition;
import cn.dinxian.entity.MyProcessInstance;
import feign.Response;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 汇讯数码科技(深圳)有限公司
 * 创建日期:2020/10/23-9:52
 * 版本   开发者     日期
 * 1.0    Danny    2020/10/23
 */

@Service
@Slf4j
public class ProcessDefinitionServiceImpl implements IProcessDefinitionService {

  @Autowired
  private RepositoryService repositoryService;

  @Autowired
  private ActReDeploymentMapper actReDeploymentMapper;
  @Autowired
  private HistoryService historyService;
  @Autowired
  private RuntimeService runtimeService;

  @Autowired
  private DeploymentService deploymentService;

  /**
   * 流程的名称和流程的关键字查询读书
   * @param processDefinition
   * @param pageDomain
   * @return
   */
  @Override
  public Page<MyProcessDefinition> selectProcessDefinitionList(ProcessDefinitionDTO processDefinition, PageDomain pageDomain) {
    
    Page<MyProcessDefinition> list = new Page<>();
    final MyProcessDefinition entity = MyProcessDefinition.builder()
        .name(processDefinition.getName())
        .key(processDefinition.getKey())
        .build();
    entity.setCurrent(pageDomain.getPageNum());
    entity.setPageSize(pageDomain.getPageSize());

    List<MyProcessDefinition>   processDefinitions = repositoryService.selectProcessDefinitionList(entity);
    

   
    long count = processDefinitions.size();
    list.setTotal(count);
    if (count!=0) {
      Set<String> ids = processDefinitions.parallelStream().map(pdl -> pdl.getDeploymentId()).collect(Collectors.toSet());
        List<ActReDeploymentVO> actReDeploymentVOS = deploymentService.selectDeployment(ActReDeploymentVO.builder()
                .setid(ids)
            .build());
      log.info("[MYLOG]:-----ProcessDefinitionServiceImpl/selectProcessDefinitionList==>actReDeploymentVOS:["+ JSONObject.toJSONString(actReDeploymentVOS)+"]");
      //匹配数据
       processDefinitions.parallelStream().forEach(pd -> pd.setDeploymentTime( 
           actReDeploymentVOS.parallelStream().filter( ac -> pd.getDeploymentId().equals(ac.getId())).findAny().orElse(new ActReDeploymentVO()).getDeployTime())
                    );

        list.addAll(processDefinitions);
            
    }
    return list;

  }

  @Override
  public MyProcessDefinition getDefinitionsByInstanceId(String instanceId) {

    final MyProcessInstance data = runtimeService.processInstanceQuery(
        MyProcessInstance.builder()
            .processInstanceId(instanceId)
            .processDefinitionKey("leave")
            .singleOrList(true)
            .build()).getData();
    String deploymentId = data.getDeploymentId();
      //get Def msg
     MyProcessDefinition processDefinition = repositoryService.ProcessDefinition(
            MyProcessDefinition.builder()
                .deploymentId(data.getDeploymentId())
                .build()
    ).getData();
    return processDefinition;
    
  }

  @Override
  public Integer deleteProcessDefinitionById(String id) {

    final CommonResult<MyProcessDefinition> result = repositoryService.deleteProcessDefinition(
        MyProcessDefinition.builder().id(id).build());
    if (result.getCode()==200){
      return 1;
    }
    return 0;
   
   
  }

  @Override
  public void uploadStreamAndDeployment(MultipartFile file) throws IOException {
    //----------1
    //部署流程
    repositoryService.uploadStreamAndDeployment(file);
   
  }

  @Override
  public void suspendOrActiveApply(String id, Integer suspendState) {
    //----------2

    // 当流程定义被挂起时，已经发起的该流程定义的流程实例不受影响（如果选择级联挂起则流程实例也会被挂起）。
    // 当流程定义被挂起时，无法发起新的该流程定义的流程实例。
    // 直观变化：act_re_procdef 的 SUSPENSION_STATE_ 为 2
    repositoryService.suspendOrActiveApply(MyProcessDefinition.builder()
        .id(id)
            .suspendState(String.valueOf(suspendState))
        .build());
  }

  @Override
  public String upload(MultipartFile multipartFile) throws IOException {
    return FileUploadUtils.upload(RuoYiConfig.getUploadPath() + "/processDefinition",
        multipartFile);
  }

  @Override
  public void addDeploymentByString(String stringBPMN) {
    //----------3
    repositoryService.addDeploymentByString(MyProcessDefinition.builder().description(stringBPMN).build());
  }

  @Override
  public void getProcessDefineXML(HttpServletResponse response, String deploymentId,
      String resourceName) throws IOException {
     BaseDTO build = BaseDTO.builder()
        .s1(deploymentId)
        .s2(resourceName)
        .build();
     Response resourceAsStream = repositoryService.getResourceAsStream(build);

    //将返回流中的body数据转为输入流
    final InputStream inputStream = resourceAsStream.body().asInputStream();
  
    int count = inputStream.available();
    byte[] bytes = new byte[count];
    response.setContentType("text/xml");
    OutputStream outputStream = response.getOutputStream();
    while (inputStream.read(bytes) != -1) {
        outputStream.write(bytes);
    }
    inputStream.close();
  }

  @Override
  public void startFlowbyName(String name) throws IOException {
    //----------3
    final CommonResult<MyProcessInstance> resultHttp = runtimeService.createProcessInstance(
        MyProcessInstance.builder()
            .processDefinitionKey("myEvection").build() );
     MyProcessInstance instance = resultHttp.getData();
    // 输出内容
    System.out.println("流程定义ID:" + instance.getProcessDefinitionId());
    System.out.println("流程实例的ID:" + instance.getId());
    System.out.println("当前活动的ID:" + instance.getActivityId());
  }

  @Override
  public String getvarious(String id, String name) {
    //----------5
    final String processInstanceDescription = runtimeService.getvarious(MyProcessInstance.builder()
        .id(id)
        .name(name)
        .build()).getData().getProcessInstanceDescription();
    return processInstanceDescription;
  }
}
